{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 《强化学习：原理与Python实现》更新与勘误\n",
    "\n",
    "（2020年11月第1版第5次印刷）\n",
    "\n",
    "### 行数计算方法\n",
    "\n",
    "本勘误文档中，行数计算“第$i$行”（$i=0,1,2,\\ldots$）是从0开始计数的。小节标题、公式、内联代码、注意、本章要点记入行数，章标题、图、表、代码清单及它们的题注不计入行数。空行不计入行数。\n",
    "\n",
    "$\n",
    "\\newcommand{\\sfA}{\\unicode{x1d608}}\n",
    "\\newcommand{\\sfS}{\\unicode{x1d61a}}\n",
    "\\newcommand{\\sfa}{\\unicode{x1d622}}\n",
    "\\newcommand{\\sfs}{\\unicode{x1d634}}\n",
    "\\newcommand{\\bftheta}{\\pmb{\\unicode{x3B8}}}\n",
    "\\newcommand{\\E}{\\textrm{E}}\n",
    "$\n",
    "\n",
    "\n",
    "## 第17页第6行\n",
    "\n",
    "作者注：\n",
    "“轨道”又称为“轨迹”。本书中这两个词混用。\n",
    "\n",
    "\n",
    "\n",
    "## 第30页\n",
    "\n",
    "作者注：用线性规划求解最优状态价值的详细证明可见《Markov Decision Processes: Discrete Stochastic Dynamic Programming》（Martin Puterman）的第6.9节。证明大致如下：当$c\\left(\\sfs\\right)$为Markov决策过程的初始状态分布时，原问题和对偶问题的目标都是Markov决策过程的平均回合奖励，原问题的最优解是最优状态价值。对$c\\left(\\sfs\\right)$做灵敏度分析可知，无论$c\\left(\\sfs\\right)$取什么分布，对偶问题均有解（这利用到对偶问题的可行域就是带折扣的状态动作对组成的分布所在的空间），所以原问题的最优解都是不变的。也就是说，Markov决策过程的最优状态价值和初始状态分布无关。进一步，可以在原问题中放宽$\\sum\\nolimits_{\\sfs}c\\left(\\sfs\\right)=1$这个限制，原问题的解依然不变，只是优化目标进行了放缩。\n",
    "\n",
    "\n",
    "## 第118页\n",
    "\n",
    "作者注：\n",
    "\n",
    "砖瓦编码是一种历史悠久的特征构造方法，可用于回归、分类等问题。目前学术界倾向于用神经网络代替砖瓦编码来构造特征。由于砖瓦编码和强化学习没有直接关联，本书没有用过多的篇幅介绍砖瓦编码。\n",
    "\n",
    "实际使用砖瓦编码时，不需要精确计算砖瓦的数量，常随意的大致估计砖瓦的数量作为特征数。如果设置的特征数大于真实的砖瓦数量，那么有些特征永远不会取到，有些浪费；如果设置的特征数小于真实的砖瓦数量，那么有多个砖瓦需要共享特征，具体逻辑可以见代码清单6-3中“冲突处理”部分。这些浪费和冲突往往不会造成明显的性能损失。\n",
    "\n",
    "第118页砖瓦数计算：每个大网格的网格宽度刚好是整个取值范围的1/8。所以，第0层大网格每个维度有8个大网格；第1~7层由于有偏移，每个维度需要有9个大网格才能覆盖整个取值范围。第117页图6-3b的情况略有不同：这个图中每个维度的取值范围不是大网格的长度的整数倍。所以有些层偏移后，不需要更多的大网格也可以覆盖整个取值范围。\n",
    "\n",
    "\n",
    "## 第128页第10行\n",
    "\n",
    "增量$\\alpha\\gamma^tG_t\\nabla\\pi\\left(\\sfA_t|\\sfS_t;\\bftheta_t\\right)$\n",
    "\n",
    "#### 改为\n",
    "\n",
    "增量$\\alpha\\gamma^tG_t\\nabla\\pi\\left(\\sfA_t|\\sfS_t;\\bftheta\\right)$\n",
    "\n",
    "\n",
    "## 第137页代码清单7-1中`learn()`函数\n",
    "\n",
    "```\n",
    "            y = np.eye(self.action_n)[df['action']] * \\\n",
    "                    df['psi'].values[:, np.newaxis]\n",
    "            self.policy_net.fit(x, y, verbose=0)\n",
    "```\n",
    "\n",
    "#### 改为\n",
    "\n",
    "```\n",
    "            sample_weight = df['psi'].values[:, np.newaxis]\n",
    "            y = np.eye(self.action_n)[df['action']]\n",
    "            self.policy_net.fit(x, y, sample_weight=sample_weight, verbose=0)\n",
    "```\n",
    "\n",
    "\n",
    "## 第142页算法8.3第2.3.2步\n",
    "\n",
    "作者注：这里的更新式子遵循了论文原文而没有考虑累积折扣。推导出现折扣是正确的；更新时考虑折扣也是正确和合理的。\n",
    "\n",
    "\n",
    "\n",
    "## 第174页第4行\n",
    "\n",
    "$\\rho_\\pi\\left(\\sfs\\right)=\\int\\limits_{\\sfs_0\\in\\mathcal{S}}p_{\\sfS_0}\\left(\\sfs_0\\right)\\sum\\limits_{t=0}^{+\\infty}\\gamma_t\\Pr\\left[\\sfS_t|\\sfS_0=\\sfs_0;\\bftheta\\right]\\mathrm{d}\\sfs_0$\n",
    "\n",
    "#### 改为\n",
    "\n",
    "$\\rho_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs\\right)=\\sum\\limits_{t=0}^{+\\infty}\\gamma_t\\Pr\\left[\\sfS_t=\\sfs;\\pi\\left(\\bftheta\\right)\\right]$, $\\sfs\\in\\mathcal{S}$\n",
    "\n",
    "作者注：从严格意义上说，有折扣的状态分布并不是概率分布，因为它的和不总是1。针对有折扣的状态分布的期望也只是采用了期望的形式。\n",
    "\n",
    "\n",
    "## 第174页第7~11行\n",
    "\n",
    "$=\\sum\\limits_{t=0}^{+\\infty}\\int\\limits_{\\sfs}p_{\\sfS_t}\\left(\\sfs\\right)\\gamma^t\\nabla\\pi\\left(\\sfs;\\bftheta\\right)\\left[\\nabla_\\sfs{q}_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs,\\sfa\\right)\\right]_{\\sfa=\\pi\\left(\\sfS_t;\\bftheta\\right)}\\mathrm{d}\\sfs$\n",
    "\n",
    "$=\\sum\\limits_{t=0}^{+\\infty}\\int\\limits_{\\sfs}\\left(\\int_{\\sfs_0}\\int\\limits_{\\sfs_0}p_{\\sfS_0}\\left(\\sfs_0\\right)\\Pr\\left[\\sfS_t=\\sfs|\\sfs_0=\\sfs_0;\\bftheta\\right]\\mathrm{d}\\sfs_0\\right)\\gamma^t\\nabla\\pi\\left(\\sfs;\\bftheta\\right)\\left[\\nabla_\\sfs{q}_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs,\\sfa\\right)\\right]_{\\sfa=\\pi\\left(\\sfs;\\bftheta\\right)}\\mathrm{d}\\sfs$\n",
    "\n",
    "$=\\int\\limits_{\\sfs}\\left(\\int\\limits_{\\sfs_0}p_{\\sfS_0}\\left(\\sfs_0\\right)\\sum\\limits_{t=0}^{+\\infty}\\gamma^t\\Pr\\left[\\sfS_t=\\sfs|\\sfs_0=\\sfs_0;\\bftheta\\right]\\mathrm{d}\\sfs_0\\right)\\nabla\\pi\\left(\\sfS_t;\\bftheta\\right)\\left[\\nabla_\\sfa{q}_{\\pi\\left(\\bftheta\\right)}\\right]_{\\sfa=\\pi\\left(\\sfs;\\bftheta\\right)}\\mathrm{d}\\sfs$\n",
    "\n",
    "$=\\int\\limits_{\\sfs}\\rho_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs\\right)\\nabla\\pi\\left(\\sfs;\\bftheta\\right)\\left[\\nabla_\\sfa{q}_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs,\\sfa\\right)\\right]_{\\sfa=\\pi\\left(\\sfs;\\bftheta\\right)}\\mathrm{d}\\sfs$\n",
    "\n",
    "$=\\E_{\\rho_{\\pi\\left(\\bftheta\\right)}}\\left[\\nabla\\pi\\left(\\sfs;\\bftheta\\right)\\left[\\nabla_\\sfa{q}_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs,\\sfa\\right)\\right]_{\\sfa=\\pi\\left(\\sfs;\\bftheta\\right)}\\right]$\n",
    "\n",
    "#### 改为\n",
    "\n",
    "$=\\sum\\limits_{t=0}^{+\\infty}\\sum\\limits_{\\sfs}^{}\\Pr\\left[\\sfS_t=\\sfs;\\pi\\left(\\bftheta\\right)\\right]\\gamma^t\\nabla\\pi\\left(\\sfs;\\bftheta\\right)\\left[\\nabla_\\sfa{q}_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs,\\sfa\\right)\\right]_{\\sfa=\\pi\\left(\\sfs;\\bftheta\\right)}$\n",
    "\n",
    "$=\\sum\\limits_{\\sfs}^{}\\left(\\sum\\limits_{t=0}^{+\\infty}\\gamma^t\\Pr\\left[\\sfS_t=\\sfs;\\pi\\left(\\bftheta\\right)\\right]\\right)\\nabla\\pi\\left(\\sfs;\\bftheta\\right)\\left[\\nabla_\\sfa{q}_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs,\\sfa\\right)\\right]_{\\sfa=\\pi\\left(\\sfs;\\bftheta\\right)}$\n",
    "\n",
    "$=\\sum\\limits_{\\sfs}^{}\\rho_{\\pi\\left(\\bftheta\\right)}\\left(\\sfs\\right)\\nabla\\pi\\left(\\sfs;\\bftheta\\right)\\left[\\nabla_\\sfa{q}_{\\pi\\left(\\bftheta\\right)}\\right]_{\\sfa=\\pi\\left(\\sfs;\\bftheta\\right)}$\n",
    "\n",
    "$=\\E_{\\rho_{\\pi\\left(\\bftheta\\right)}}\\left[\\nabla\\pi\\left(\\sfS;\\bftheta\\right)\\left[\\nabla_\\sfa{q}_{\\pi\\left(\\bftheta\\right)}\\left(\\sfS,\\sfa\\right)\\right]_{\\sfa=\\pi\\left(\\sfS;\\bftheta\\right)}\\right]$"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
